/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2012 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/
package info.geometrixx.outdoors.core.util;

import com.day.cq.wcm.api.NameConstants;
import com.day.cq.wcm.api.Page;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;

import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A class providing various helper functions for Geometrixx Outdoors.
 */
public class GeoHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(GeoHelper.class);

    /**
     * Tells if a string is empty or contains only white space characters
     * (characters with a code greater than '\u0020').
     * @param str   The string to be checked
     * @return      <code>true</code> if the string is null, or contains only whitespace characters.
     *              <code>false</code> otherwise.
     */
    public static boolean isEmpty(final String str) {
        return (str == null || str.trim().length() == 0);
    }

    /**
     * Tells if a string is not empty and contains other characters than white spaces
     * (characters with a code greater than '\u0020').
     * @param str   The string to be checked.
     * @return      <code>true</code> if the string is not null, and contains non-whitespace characters.
     *              <code>false</code> otherwise.
     */
    public static boolean notEmpty(final String str) {
        return (str != null && str.trim().length() > 0);
    }

    /**
     * Returns the title of the given resource. If the title is empty it will fallback to the page title, title,
     * or name of the given page.
     * @param resource  The resource.
     * @param page      The page to fallback to.
     * @return          The best suited title found (or <code>null</code> if resource is <code>null</code>).
     */
    public static String getTitle(final Resource resource, final Page page) {
        if (resource != null) {
            final ValueMap properties = resource.adaptTo(ValueMap.class);
            if (properties != null) {
                final String title = properties.get(NameConstants.PN_TITLE, String.class);
                if (notEmpty(title)) {
                    return title;
                } else {
                    return getPageTitle(page);
                }
            }
        } else {
            LOGGER.debug("Provided resource argument is null");
        }
        return null;
    }

    /**
     * Returns the page title of the given page. If the page title is empty it will fallback to the title and to the
     * name of the page.
     * @param page  The page.
     * @return      The best suited title found (or <code>null</code> if page is <code>null</code>).
     */
    public static String getPageTitle(final Page page) {
        if (page != null) {
            final String title = page.getPageTitle();
            if (isEmpty(title)) {
                return GeoHelper.getTitle(page);
            }
            return title;
        } else {
            LOGGER.debug("Provided page argument is null");
            return null;
        }
    }

    /**
     * Returns the navigation title of the given page. If the navigation title is empty it will fallback to the title
     * and to the name of the page.
     * @param page  The page.
     * @return      The best suited title found (or <code>null</code> if page is <code>null</code>).
     */
    public static String getNavTitle(final Page page) {
        if (page != null) {
            final String title = page.getNavigationTitle();
            if (isEmpty(title)) {
                return GeoHelper.getTitle(page);
            }
            return title;
        } else {
            LOGGER.debug("Provided page argument is null");
            return null;
        }
    }

    /**
     * Returns the title of the given page. If the title is empty it will fallback to the name of the page.
     * @param page  The page.
     * @return      The best suited title found (or <code>null</code> if page is <code>null</code>).
     */
    public static String getTitle(final Page page) {
        if (page != null) {
            final String title = page.getTitle();
            if (isEmpty(title)) {
                return page.getName();
            }
            return title;
        } else {
            LOGGER.debug("Provided page argument is null");
            return null;
        }
    }

    /**
     * Searches for a resource of a specific type in the given resource tree. This function will also return resources
     * which super type(s) equals the given resource type.
     * @param resource      The resource where to search.
     * @param resourceType  The resource type that should be searched for.
     * @return              The first resource of the given type that was found, or <code>null</code> if not found.
     */
    public static Resource findResourceType(Resource resource, String resourceType) {
        if (resource != null && resourceType != null) {
            if (resource.isResourceType(resourceType)) {
                return resource;
            }
            Iterator<Resource> children = resource.listChildren();
            while (children.hasNext()) {
                final Resource child = children.next();
                final Resource found = findResourceType(child, resourceType);
                if (found != null) {
                    return found;
                }
            }
        } else {
            if (resource == null) {
                LOGGER.debug("Provided resource argument is null");
            }
            if (resourceType == null) {
                LOGGER.debug("Provided resourceType argument is null");
            }
        }
        return null;
    }
}